/*
	GrammarAnalyze.h
	Define structs and classes used in GrammarAnalyze

	@author Wolfhead
*/

#pragma once

#ifndef _GRAMMAR_ANALYZE_H_
#define _GRAMMAR_ANALYZE_H_

#include <vector>
#include <map>
#include <set>
#include "../Production/ProductionBasic.h"
#include "ParserStatus.h"


typedef struct _structItemLink
{
	Token_Type	Token;
	int			ItemIndex;
}ItemLink;


#define UNGROUPED_ITEM (-1) 


MAKE_PTR(CItem);

class CItem
{
public:
	static CItemPtr create()
	{
		return CItemPtr(new CItem());
	}
public:
	CProductionPtr pProduction;
	int Position;
	bool Reduce;
};

class CGrammarAnalyze
{
public:
	typedef std::set<CItemPtr> ItemClosure;

public:
	CGrammarAnalyze(std::vector<CProductionPtr>& productions);
	~CGrammarAnalyze();

public:

	std::vector<CParserStatusPtr> Analyze();

private:
	void PopulateItems();
	void PopulateClosures();
	void PopulateParserStatusTable();
    void PopulateFirst();
    void PopulateFollow();
    void LogFollow();
    void LogFirst();
	void LogItems();
	void LogProductions();
	void LogClosures();
	void LogParserStatus();

	int GetProductionIndex(CProductionPtr pProduction);

	void Closure(ItemClosure& closure);
    ItemClosure Go(ItemClosure& closure, Token_Type Token);

    bool HasEmptyProduction(Token_Type Token);

private:
	CItemPtr m_pStartItem;
	std::vector<CItemPtr> m_Items;
	std::vector<CProductionPtr>& m_productions;
	std::vector<ItemClosure> m_Closures;
	std::vector<CParserStatusPtr> m_ParserStatusTable;
    std::map<Token_Type , std::set<Token_Type> > m_First;
    std::map<Token_Type , std::set<Token_Type> > m_Follow;
};

#endif //#ifndef _GRAMMAR_ANALYZE_H_